<?php
/**
 * Created by 长毋相忘c.
 * 文件用途描述 :
 * Date: 2018/2/19/019
 * Time: 14:07
 */

namespace app\api\service;

use app\api\model\OrderProduct;
use app\api\model\Order as OrderModel;
use app\api\model\Product;
use app\api\model\UserAddress;
use app\lib\enum\OrderStatusEnum;
use app\lib\exception\OrderException;
use app\lib\exception\UserException;
use think\Db;

class Order
{
    // 订单的商品列表，也就是客户端传递过来的products参数
    protected $oProducts;
    // 真实的商品信息（包括库存量）
    protected $products;

    protected $uid;

    //库存量检测
    public function place($uid,$oProducts){
        //oProduct和Product作对比
        //Product从数据库例查询出来
        $this->oProducts=$oProducts;
        $this->products=$this->getProductsByOrder($oProducts);
        $this->uid=$uid;
        $status=$this->getOrderStatus();
        //如果订单没通过则返回错误订单状态
        if(!$status['pass'])
        {
            $status['order_id'] = -1;
            return $status;
        }
            //如果订单检测成功，则创建订单
        $orderSnap=$this->snapOrder($status);
        $order=$this->createOrder($orderSnap);
        $order['pass']=true;
        return $order;
    }

    private function createOrder($snap){
        Db::startTrans();
        try{
            //准备订单数据，并存入订单表
            $orderNo = $this->makeOrderNo();
            $order = new OrderModel();
            $order->user_id = $this->uid;
            $order->order_no = $orderNo;
            $order->total_price = $snap['orderPrice'];
            $order->total_count = $snap['totalCount'];
            $order->snap_img = $snap['snapImg'];
            $order->snap_name = $snap['snapName'];
            $order->snap_address = $snap['snapAddress'];
            $order->snap_items = json_encode($snap['pStatus']);
         //   $order->create_time=time();
            $order->save();

            //准备Order_Product数据
            $orderID = $order->id;
            $create_time = $order->create_time;

            //将OrderID赋值给客户端传来的数组 必须加&才能更改！
            foreach ($this->oProducts as &$p){
                $p['order_id'] = $orderID;
            }
            //创建关系表模型，并保存
            $orderProduct = new OrderProduct();
            $orderProduct->saveAll($this->oProducts);
            Db::commit();
            return [
                'order_no' => $orderNo,
                'order_id' => $orderID,
                'create_time' => $create_time
            ];
        }catch (Exception $ex){
            Db::rollback();
            throw $ex;
        }

    }

    //生成订单号
    public static function makeOrderNo(){
        $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $orderSn =
            $yCode[intval(date('Y')) - 2017] .
            strtoupper(dechex(date('m'))) .
            date('d') .
            substr(time(), -5) .
            substr(microtime(), 2, 5) .
            sprintf('%02d', rand(0, 99));
        return $orderSn;
    }

    //生成订单快照
    private function snapOrder($status){
        $snap = [
            'orderPrice' => 0, //订单总价
            'totalCount' => 0, //订单商品总数量
            'pStatus' => [], //所有商品的状态
            'snapAddress' => null, //用户的收货地址
            'snapName' => '', //订单缩略名
            'snapImg' => '' //订单缩略图
        ];
        $snap['orderPrice'] = $status['orderPrice'];
        $snap['totalCount'] = $status['totalCount'];
        $snap['pStatus'] = $status['pStatusArray'];
        $snap['snapAddress'] = json_encode($this->getUserAddress());
        $snap['snapName'] = $this->products[0]['name'];
        $snap['snapImg'] = $this->products[0]['main_img_url'];

        if(count($this->products) > 1){
            $snap['snapName'] .= '等';
        }
        return $snap;
    }

    //获取用户地址
    private function getUserAddress(){
        $userAddress = UserAddress::where('user_id','=',$this->uid)
            ->find();
        if (!$userAddress){
            throw new UserException([
                'msg' => '用户收获地址不存在，下单失败',
                'errorCode' => 60001
            ]);
        }
        return $userAddress->toArray();
    }

    //获取订单状态
    private function getOrderStatus(){
        $status = [
            'pass' => true, //表示订单检测是否通过
            'orderPrice' => 0,//所有商品价格总和
            'totalCount' => 0,//商品总个数
            'pStatusArray' => []//所有商品的详细信息

        ];
       //检测商品真实库存够不够
        foreach ($this->oProducts as $oProduct){
            $pStatus = $this->getProductStatus(
                $oProduct['product_id'],$oProduct['count'],$this->products);
            if (!$pStatus['havaStock']){
                $status['pass'] = false;
            }
            $status['orderPrice'] += $pStatus['totalPrice'];
            $status['totalCount'] += $pStatus['counts'];
            array_push($status['pStatusArray'],$pStatus);
        }
        return $status;
    }

    //获取商品状态
    private function getProductStatus($oPID,$oCount,$products){
        //用于确定当前$oPID在下单数组里的序号
        $pIndex = -1;

        //保存订单内某一商品的详细信息
        $pStatus = [
            'id' => null, //商品ID
            'haveStock' => false,  //库存量够不够
            'counts' => 0, //当前订单请求地商品数量
            'price' => 0,
            'name' => '', //商品的名字
            'totalPrice' => 0, //订单的总价格
            'main_img_url' => null
        ];
        //通过循环看能不能在数据库中找到对应商品
        for ($i=0;$i<count($products);$i++){
            if ($oPID == $products[$i]['id']){
                $pIndex = $i;
            }
        }
        //如果在数据库中查不到此商品
        if ($pIndex == -1){
            throw new OrderException([
                'msg' => 'id为'.$oPID.'商品不存在，创建订单失败'
            ]);
        }else{
            $product = $products[$pIndex];
            $pStatus['id'] = $product['id'];
            $pStatus['name'] = $product['name'];
            $pStatus['counts'] = $oCount;
            $pStatus['price'] = $product['price'];
            $pStatus['main_img_url'] = $product['main_img_url'];
            $pStatus['totalPrice'] = $product['price'] * $oCount;
            //判断库存量如果>=0则有库存 降库存变为true
            if ($product['stock'] - $oCount >= 0){
                $pStatus['havaStock'] = true;
            }
        }

        return $pStatus;
    }

    public function checkOrderStock($orderID){
        $oProducts = OrderProduct::where('order_id','=',$orderID)
            ->select();
        $this->oProducts = $oProducts;

        $this->products = $this->getProductsByOrder($oProducts);
        $status = $this->getOrderStatus();
        return $status;
    }

    //根据订单信息查找真实商品信息
    private function getProductsByOrder($oProducts){
        //通过循环查询数据库不可取
//        foreach ($oProducts as $oProduct){
//            //循环查询数据库
//        }
        $oPIDs=[]; //用来存储product_id
        foreach ($oProducts as $item)
        {
            array_push($oPIDs, $item['product_id']);
        }

        $products=Product::all($oPIDs)
            ->visible(['id', 'price', 'stock', 'name', 'main_img_url'])
            ->toArray();
        return $products;
    }

    public function delivery($orderID, $jumpPage = '')
    {
        $order = OrderModel::where('id', '=', $orderID)
            ->find();
        if (!$order) {
            throw new OrderException();
        }
        if ($order->status != OrderStatusEnum::PAID) {
            throw new OrderException([
                'msg' => '还没付款呢，想干嘛？或者你已经更新过订单了，不要再刷了',
                'errorCode' => 80002,
                'code' => 403
            ]);
        }
        $order->status = OrderStatusEnum::DELIVERED;
        $order->save();
//            ->update(['status' => OrderStatusEnum::DELIVERED]);
        $message = new DeliveryMessage();
        return $message->sendDeliveryMessage($order, $jumpPage);
    }
}